From bf2c44f8b469835338e185fac93399fd34dff6e3 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 28 Sep 2009 10:01:10 +0100 Subject: [PATCH] x86: Allow TSC mode (emulate vs native) to be configured per domain. The default is to emulate. Old saved images will be restored with legacy behaviour however (native TSC, no emulation). Signed-off-by: Dan Magenheimer Signed-off-by: Keir Fraser --- tools/libxc/xc_domain.c | 9 +++++ tools/libxc/xenctrl.h | 2 ++ tools/python/xen/lowlevel/xc/xc.c | 22 ++++++++++++ tools/python/xen/xend/XendConfig.py | 4 +++ tools/python/xen/xend/XendDomainInfo.py | 7 +++- tools/python/xen/xm/create.py | 9 ++++- tools/python/xen/xm/xenapi_create.py | 1 + xen/arch/x86/domain.c | 2 -- xen/arch/x86/domctl.c | 20 +++++++++++ xen/arch/x86/hvm/hvm.c | 48 ++++++++++++++----------- xen/arch/x86/hvm/save.c | 11 +++--- xen/arch/x86/hvm/svm/svm.c | 11 +++++- xen/arch/x86/hvm/svm/vmcb.c | 2 +- xen/arch/x86/hvm/vmx/vmcs.c | 6 +++- xen/arch/x86/hvm/vmx/vmx.c | 10 +++--- xen/arch/x86/hvm/vpt.c | 2 +- xen/arch/x86/time.c | 34 ++++++++++++------ xen/include/asm-x86/domain.h | 2 ++ xen/include/asm-x86/hvm/hvm.h | 4 +-- xen/include/asm-x86/time.h | 1 - xen/include/public/domctl.h | 7 +++- 21 files changed, 160 insertions(+), 54 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 6ed4f52ec3..61cde9af39 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -466,6 +466,15 @@ int xc_domain_set_time_offset(int xc_handle, return do_domctl(xc_handle, &domctl); } +int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native) +{ + DECLARE_DOMCTL; + domctl.cmd = XEN_DOMCTL_set_tsc_native; + domctl.domain = (domid_t)domid; + domctl.u.set_tsc_native.is_native = is_native; + return do_domctl(xc_handle, &domctl); +} + int xc_domain_memory_increase_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 1eade658a0..81ba26d616 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -628,6 +628,8 @@ int xc_domain_set_time_offset(int xc_handle, uint32_t domid, int32_t time_offset_seconds); +int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native); + int xc_domain_memory_increase_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index c7b484f983..3bff6a7f97 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1459,6 +1459,20 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args) return zero; } +static PyObject *pyxc_domain_set_tsc_native(XcObject *self, PyObject *args) +{ + uint32_t dom, is_native; + + if (!PyArg_ParseTuple(args, "ii", &dom, &is_native)) + return NULL; + + if (xc_domain_set_tsc_native(self->xc_handle, dom, is_native) != 0) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_domain_send_trigger(XcObject *self, PyObject *args, PyObject *kwds) @@ -1981,6 +1995,14 @@ static PyMethodDef pyxc_methods[] = { " offset [int]: Time offset from UTC in seconds.\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_set_tsc_native", + (PyCFunction)pyxc_domain_set_tsc_native, + METH_VARARGS, "\n" + "Set a domain's TSC mode (emulate vs native)\n" + " dom [int]: Domain whose TSC mode is being set.\n" + " is_native [int]: 1=native, 0=emulate.\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_send_trigger", (PyCFunction)pyxc_domain_send_trigger, METH_VARARGS | METH_KEYWORDS, "\n" diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index d5cd17cf1b..9c84c26c65 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -162,6 +162,7 @@ XENAPI_PLATFORM_CFG_TYPES = { 'vncdisplay': int, 'vnclisten': str, 'timer_mode': int, + 'tsc_native': int, 'vpt_align': int, 'viridian': int, 'vncpasswd': str, @@ -473,6 +474,9 @@ class XendConfig(dict): if not os.path.exists(self['platform']['device_model']): raise VmError("device model '%s' not found" % str(self['platform']['device_model'])) + if 'tsc_native' not in self['platform']: + self['platform']['tsc_native'] = 0 + if self.is_hvm(): if 'timer_mode' not in self['platform']: self['platform']['timer_mode'] = 1 diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index b7a4307ebb..b38a5fea4b 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2423,7 +2423,12 @@ class XendDomainInfo: self._recreateDom() - # Set timer configration of domain + # Set TSC mode of domain + tsc_native = self.info["platform"].get("tsc_native") + if arch.type == "x86" and tsc_native is not None: + xc.domain_set_tsc_native(self.domid, tsc_native) + + # Set timer configuration of domain timer_mode = self.info["platform"].get("timer_mode") if hvm and timer_mode is not None: xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE, diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index d7ed07b3c6..14f8aa6425 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -221,6 +221,10 @@ gopts.var('timer_mode', val='TIMER_MODE', use="""Timer mode (0=delay virtual time when ticks are missed; 1=virtual time is always wallclock time.""") +gopts.var('tsc_native', val='TSC_NATIVE', + fn=set_int, default=0, + use="""TSC mode (0=emulate TSC, 1=native TSC).""") + gopts.var('vpt_align', val='VPT_ALIGN', fn=set_int, default=1, use="Enable aligning all periodic vpt to reduce timer interrupts.") @@ -715,6 +719,9 @@ def configure_image(vals): if vals.suppress_spurious_page_faults: config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults]) + if vals.tsc_native is not None: + config_image.append(['tsc_native', vals.tsc_native]) + return config_image def configure_disks(config_devs, vals): @@ -984,7 +991,7 @@ def make_config(vals): config.append([n, v]) map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory', - 'restart', 'on_poweroff', + 'restart', 'on_poweroff', 'tsc_native', 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features', 'on_xend_start', 'on_xend_stop', 'target', 'cpuid', 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults']) diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index 27702635ae..903b29d21a 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -1066,6 +1066,7 @@ class sxp2xml: 'pci_msitranslate', 'pci_power_mgmt', 'xen_platform_pci', + 'tsc_native' ] platform_configs = [] diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 85e0ba0d59..d9d6fb075e 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -520,8 +520,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) d->arch.cpuids[i].input[1] = XEN_CPUID_INPUT_UNUSED; } - /* For now, per-domain SoftTSC status is taken from global boot param. */ - d->arch.vtsc = opt_softtsc; spin_lock_init(&d->arch.vtsc_lock); return 0; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index cb5bec7f71..c5684c9a22 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1060,6 +1060,26 @@ long arch_do_domctl( } break; + case XEN_DOMCTL_set_tsc_native: + { + struct domain *d; + + ret = -ESRCH; + d = rcu_lock_domain_by_id(domctl->domain); + if ( d == NULL ) + break; + + domain_pause(d); + d->arch.vtsc = !domctl->u.set_tsc_native.is_native; + if ( is_hvm_domain(d) ) + hvm_set_rdtsc_exiting(d, d->arch.vtsc || hvm_gtsc_need_scale(d)); + domain_unpause(d); + + rcu_unlock_domain(d); + ret = 0; + } + break; + case XEN_DOMCTL_suppress_spurious_page_faults: { struct domain *d; diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 7748b4579e..b4e3708ca7 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -142,23 +142,23 @@ uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2) return TRAP_double_fault; } -void hvm_enable_rdtsc_exiting(struct domain *d) +void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable) { struct vcpu *v; - if ( opt_softtsc || !hvm_funcs.enable_rdtsc_exiting ) - return; - for_each_vcpu ( d, v ) - hvm_funcs.enable_rdtsc_exiting(v); + hvm_funcs.set_rdtsc_exiting(v, enable); } int hvm_gtsc_need_scale(struct domain *d) { uint32_t gtsc_mhz, htsc_mhz; + if ( d->arch.vtsc ) + return 0; + gtsc_mhz = d->arch.hvm_domain.gtsc_khz / 1000; - htsc_mhz = opt_softtsc ? 1000 : ((uint32_t)cpu_khz / 1000); + htsc_mhz = (uint32_t)cpu_khz / 1000; d->arch.hvm_domain.tsc_scaled = (gtsc_mhz && (gtsc_mhz != htsc_mhz)); return d->arch.hvm_domain.tsc_scaled; @@ -171,38 +171,44 @@ static u64 hvm_h2g_scale_tsc(struct vcpu *v, u64 host_tsc) if ( !v->domain->arch.hvm_domain.tsc_scaled ) return host_tsc; - htsc_khz = opt_softtsc ? 1000000 : cpu_khz; + htsc_khz = cpu_khz; gtsc_khz = v->domain->arch.hvm_domain.gtsc_khz; return muldiv64(host_tsc, gtsc_khz, htsc_khz); } void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc) { - uint64_t host_tsc, scaled_htsc; + uint64_t tsc; - if ( opt_softtsc ) - host_tsc = hvm_get_guest_time(v); + if ( v->domain->arch.vtsc ) + { + tsc = hvm_get_guest_time(v); + } else - rdtscll(host_tsc); - - scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc); + { + rdtscll(tsc); + tsc = hvm_h2g_scale_tsc(v, tsc); + } - v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - scaled_htsc; + v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - tsc; hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); } u64 hvm_get_guest_tsc(struct vcpu *v) { - uint64_t host_tsc, scaled_htsc; + uint64_t tsc; - if ( opt_softtsc ) - host_tsc = hvm_get_guest_time(v); + if ( v->domain->arch.vtsc ) + { + tsc = hvm_get_guest_time(v); + } else - rdtscll(host_tsc); - - scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc); + { + rdtscll(tsc); + tsc = hvm_h2g_scale_tsc(v, tsc); + } - return scaled_htsc + v->arch.hvm_vcpu.cache_tsc_offset; + return tsc + v->arch.hvm_vcpu.cache_tsc_offset; } void hvm_migrate_timers(struct vcpu *v) diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c index af5aad7221..e409add6b6 100644 --- a/xen/arch/x86/hvm/save.c +++ b/xen/arch/x86/hvm/save.c @@ -61,15 +61,14 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr) "does not match host (%#"PRIx32").\n", hdr->cpuid, eax); /* Restore guest's preferred TSC frequency. */ - d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz; - - if ( hdr->gtsc_khz && hvm_gtsc_need_scale(d) ) + if ( hdr->gtsc_khz ) + d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz; + if ( hvm_gtsc_need_scale(d) ) { - hvm_enable_rdtsc_exiting(d); + hvm_set_rdtsc_exiting(d, 1); gdprintk(XENLOG_WARNING, "Domain %d expects freq %uMHz " "but host's freq is %luMHz: trap and emulate rdtsc\n", - d->domain_id, hdr->gtsc_khz / 1000, opt_softtsc ? 1000ul : - cpu_khz / 1000); + d->domain_id, hdr->gtsc_khz / 1000, cpu_khz / 1000); } /* VGA state is not saved/restored, so we nobble the cache. */ diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index ead3eeca31..b34289878b 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -619,6 +619,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset) v->arch.hvm_svm.vmcb->tsc_offset = offset; } +static void svm_set_rdtsc_exiting(struct vcpu *v, bool_t enable) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_RDTSC; + if ( enable ) + vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC; +} + static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) { char *p; @@ -845,7 +853,8 @@ static struct hvm_function_table svm_function_table = { .fpu_dirty_intercept = svm_fpu_dirty_intercept, .msr_read_intercept = svm_msr_read_intercept, .msr_write_intercept = svm_msr_write_intercept, - .invlpg_intercept = svm_invlpg_intercept + .invlpg_intercept = svm_invlpg_intercept, + .set_rdtsc_exiting = svm_set_rdtsc_exiting }; static int svm_cpu_up(struct cpuinfo_x86 *c) diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 6f1f087d88..202cc9810d 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -167,7 +167,7 @@ static int construct_vmcb(struct vcpu *v) /* TSC. */ vmcb->tsc_offset = 0; - if ( opt_softtsc ) + if ( v->domain->arch.vtsc ) vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC; /* Guest EFER. */ diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 11dc468521..724d0a61d3 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -133,13 +133,14 @@ static void vmx_init_vmcs_config(void) CPU_BASED_MOV_DR_EXITING | CPU_BASED_ACTIVATE_IO_BITMAP | CPU_BASED_USE_TSC_OFFSETING | - (opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0)); + CPU_BASED_RDTSC_EXITING); opt = (CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_TPR_SHADOW | CPU_BASED_MONITOR_TRAP_FLAG | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); _vmx_cpu_based_exec_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_PROCBASED_CTLS); + _vmx_cpu_based_exec_control &= ~CPU_BASED_RDTSC_EXITING; #ifdef __x86_64__ if ( !(_vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) ) { @@ -553,6 +554,9 @@ static int construct_vmcs(struct vcpu *v) __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control; + if ( d->arch.vtsc ) + v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; + v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control; if ( paging_mode_hap(d) ) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c51f560ab3..151d3a5be0 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -949,13 +949,15 @@ static void vmx_set_tsc_offset(struct vcpu *v, u64 offset) vmx_vmcs_exit(v); } -static void vmx_enable_rdtsc_exiting(struct vcpu *v) +static void vmx_set_rdtsc_exiting(struct vcpu *v, bool_t enable) { vmx_vmcs_enter(v); - v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; + v->arch.hvm_vmx.exec_control &= ~CPU_BASED_RDTSC_EXITING; + if ( enable ) + v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); vmx_vmcs_exit(v); - } +} static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) { @@ -1414,7 +1416,7 @@ static struct hvm_function_table vmx_function_table = { .invlpg_intercept = vmx_invlpg_intercept, .set_uc_mode = vmx_set_uc_mode, .set_info_guest = vmx_set_info_guest, - .enable_rdtsc_exiting = vmx_enable_rdtsc_exiting + .set_rdtsc_exiting = vmx_set_rdtsc_exiting }; static unsigned long *vpid_bitmap; diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index 9a0bb06429..22d66f6fed 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -33,7 +33,7 @@ void hvm_init_guest_time(struct domain *d) pl->stime_offset = -(u64)get_s_time(); pl->last_guest_time = 0; - d->arch.hvm_domain.gtsc_khz = opt_softtsc ? 1000000 : cpu_khz; + d->arch.hvm_domain.gtsc_khz = cpu_khz; d->arch.hvm_domain.tsc_scaled = 0; } diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index a4bb329524..f21861d7e6 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -36,9 +36,6 @@ static char __initdata opt_clocksource[10]; string_param("clocksource", opt_clocksource); -int opt_softtsc; -boolean_param("softtsc", opt_softtsc); - /* * opt_consistent_tscs: All TSCs tick at the exact same rate, allowing * simplified system time handling. @@ -1436,20 +1433,18 @@ struct tm wallclock_time(void) * PV SoftTSC Emulation. */ -static unsigned long rdtsc_kerncount, rdtsc_usercount; - void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs) { s_time_t now; if ( guest_kernel_mode(v, regs) ) { - rdtsc_kerncount++; + v->domain->arch.vtsc_kerncount++; rdtsc(regs->eax, regs->edx); } else { - rdtsc_usercount++; + v->domain->arch.vtsc_kerncount++; spin_lock(&v->domain->arch.vtsc_lock); now = get_s_time() + v->domain->arch.vtsc_stime_offset; if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 ) @@ -1462,10 +1457,28 @@ void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs) } } +/* vtsc may incur measurable performance degradation, diagnose with this */ static void dump_softtsc(unsigned char key) { - printk("softtsc count: %lu kernel, %lu user\n", - rdtsc_kerncount, rdtsc_usercount); + struct domain *d; + int domcnt = 0; + + for_each_domain ( d ) + { + if ( !d->arch.vtsc ) + continue; + if ( is_hvm_domain(d) ) + printk("dom%u (hvm) vtsc count: %"PRIu64" total\n", + d->domain_id, d->arch.vtsc_kerncount); + else + printk("dom%u vtsc count: %"PRIu64" kernel, %"PRIu64" user\n", + d->domain_id, d->arch.vtsc_kerncount, + d->arch.vtsc_usercount); + domcnt++; + } + + if ( !domcnt ) + printk("All domains have native TSC\n"); } static struct keyhandler dump_softtsc_keyhandler = { @@ -1476,8 +1489,7 @@ static struct keyhandler dump_softtsc_keyhandler = { static int __init setup_dump_softtsc(void) { - if ( opt_softtsc ) - register_keyhandler('s', &dump_softtsc_keyhandler); + register_keyhandler('s', &dump_softtsc_keyhandler); return 0; } __initcall(setup_dump_softtsc); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index cf65772ebb..6edbe3b215 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -304,6 +304,8 @@ struct arch_domain bool_t vtsc; s_time_t vtsc_last; spinlock_t vtsc_lock; + uint64_t vtsc_kerncount; /* for hvm, counts all vtsc */ + uint64_t vtsc_usercount; /* not used for hvm */ int64_t vtsc_stime_offset; } __cacheline_aligned; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 76e06d7db6..327a1c9737 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -131,7 +131,7 @@ struct hvm_function_table { void (*invlpg_intercept)(unsigned long vaddr); void (*set_uc_mode)(struct vcpu *v); void (*set_info_guest)(struct vcpu *v); - void (*enable_rdtsc_exiting)(struct vcpu *v); + void (*set_rdtsc_exiting)(struct vcpu *v, bool_t); }; extern struct hvm_function_table hvm_funcs; @@ -288,7 +288,7 @@ int hvm_event_needs_reinjection(uint8_t type, uint8_t vector); uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2); -void hvm_enable_rdtsc_exiting(struct domain *d); +void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable); int hvm_gtsc_need_scale(struct domain *d); static inline int hvm_cpu_up(void) diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index ec06313f95..dac53bcc25 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -41,7 +41,6 @@ int pit_broadcast_is_available(void); uint64_t acpi_pm_tick_to_ns(uint64_t ticks); uint64_t ns_to_acpi_pm_tick(uint64_t ns); -extern int opt_softtsc; void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs); #endif /* __X86_TIME_H__ */ diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index f7b1fc5ec7..3b4cb51796 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -401,7 +401,11 @@ struct xen_domctl_settimeoffset { typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); - +#define XEN_DOMCTL_set_tsc_native 57 +typedef struct xen_domctl_set_tsc_native { + uint32_t is_native; /* IN: 0: TSC is emulated; 1: TSC is host TSC */ +} xen_domctl_set_tsc_native_t; + #define XEN_DOMCTL_gethvmcontext 33 #define XEN_DOMCTL_sethvmcontext 34 typedef struct xen_domctl_hvmcontext { @@ -672,6 +676,7 @@ struct xen_domctl { struct xen_domctl_hypercall_init hypercall_init; struct xen_domctl_arch_setup arch_setup; struct xen_domctl_settimeoffset settimeoffset; + struct xen_domctl_set_tsc_native set_tsc_native; struct xen_domctl_real_mode_area real_mode_area; struct xen_domctl_hvmcontext hvmcontext; struct xen_domctl_hvmcontext_partial hvmcontext_partial; -- 2.30.2